home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
clang
/
tcisam.zip
/
IDELETE.C
< prev
next >
Wrap
Text File
|
1987-08-15
|
6KB
|
195 lines
/*
* IDELETE.C - delete a record
*
* Copyright (c) 1987, Jim Mischel
*/
#include "inxdefs.h"
/*
* idelete() - remove the current record from the data stream. The data
* record is not actually removed from the file and the index record is not
* removed from the index file. The index pointers are adjusted so that
* they skip over the index for this record.
* Returns 0 if successful, error status otherwise. If the key at 'source'
* is not the same as the key in the current data record, I_INVKEY is
* returned and no action is taken. Since the only integrity check
* made is a simple key comparison, if duplicate keys are permitted, it
* is possible to delete the wrong record.
*/
int idelete(void *d, void *src)
{
register df_rec *db_control = (df_rec *)d;
char *source = (char *)src;
register inx_rec *irec;
inx_rec save_inx_rec;
long save_inx_ptr;
/* see if record has already been deleted */
if (db_control->df_flags & DF_DELETE)
return(ierror(I_INVKEY));
/* see if keys are equal */
if ((*db_control->df_cmp)((source+db_control->df_key_offset),
db_control->df_key_ptr))
return(ierror(I_INVKEY)); /* error: keys not equal */
/*
* There are 3 cases to worry about:
* 1. The node is a leaf
* 2. The node has only 1 son
* 3. The node has 2 sons
*/
/* setup a pointer to the current index record */
irec = &db_control->df_inx_buff;
memcpy(&save_inx_rec,irec,sizeof(inx_rec)); /* copy current index rec */
save_inx_ptr = db_control->df_inx_ptr; /* save current index pointer */
if ((irec->if_flags & RTHRD) && (irec->if_flags & LTHRD)) {
/*
* the node has no descendents (leaf)
*/
if (iread_inx(db_control,irec->if_parent)) /* get parent node */
return(ierrno);
if (irec->if_left_node == save_inx_ptr) { /* node is a left son */
irec->if_left_node = save_inx_rec.if_left_node;
irec->if_flags |= ((save_inx_rec.if_flags & BTHRD) | LTHRD);
}
else { /* node is a right son */
irec->if_right_node = save_inx_rec.if_right_node;
irec->if_flags |= ((save_inx_rec.if_flags & ETHRD) | RTHRD);
}
if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
return(ierrno);
}
else if ((irec->if_flags & LTHRD) || (irec->if_flags & RTHRD)) {
/*
* the node has only one son
*/
long node_ptr;
int son;
if (irec->if_flags & RTHRD)
node_ptr = irec->if_left_node;
else
node_ptr = irec->if_right_node;
/* adjust parent node */
if (iread_inx(db_control,irec->if_parent))
return(ierrno);
if (irec->if_left_node == save_inx_ptr) { /* left son */
son = -1;
irec->if_left_node = node_ptr;
}
else { /* right son */
son = 1;
irec->if_right_node = node_ptr;
}
if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
return(ierrno);
/* adjust only son */
if (iread_inx(db_control,node_ptr))
return(ierrno);
if (irec->if_right_node == save_inx_ptr)
irec->if_right_node = save_inx_rec.if_parent;
else if (irec->if_left_node == save_inx_ptr)
irec->if_left_node = save_inx_rec.if_parent;
irec->if_parent = save_inx_rec.if_parent;
if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
return(ierrno);
/* adjust inorder successor/predecessor */
if (son == -1) {
if (iget_prev(db_control,&save_inx_rec))
return(ierrno);
irec->if_right_node = save_inx_ptr;
}
else {
if (iget_next(db_control,&save_inx_rec))
return(ierrno);
irec->if_left_node = save_inx_ptr;
}
if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
return(ierrno);
}
else {
/*
* the node has two sons
*/
inx_rec save_parent,
save_prev;
long save_prev_ptr;
if (iread_inx(db_control,irec->if_parent)) /* get parent node */
return(ierrno);
memcpy(&save_parent,irec,sizeof(inx_rec)); /* and save it */
/*
* the deleted node will be replaced by its inorder predecessor
*/
if (iget_prev(db_control,&save_inx_rec))
return(ierrno);
memcpy(&save_prev,irec,sizeof(inx_rec)); /* and save it */
save_prev_ptr = db_control->df_inx_ptr;
/*
* adjust the parent node to point to the replacement
*/
if (save_parent.if_right_node == save_inx_ptr) /* right son */
save_parent.if_right_node = save_prev_ptr;
else /* left son */
save_parent.if_left_node = save_prev_ptr;
if (iwrite_inx(db_control,&save_parent,save_inx_rec.if_parent))
return(ierrno);
/* update predecessor's parent */
if (iread_inx(db_control,save_prev.if_parent))
return(ierrno);
if (save_prev.if_flags & LTHRD)
irec->if_flags |= RTHRD;
else
irec->if_right_node = save_prev.if_left_node;
if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
return(ierrno);
/* update predecessor's left son (if it exists) */
if (!(save_prev.if_flags & LTHRD)) {
if (iread_inx(db_control,save_prev.if_left_node))
return(ierrno);
irec->if_parent = save_prev.if_parent;
if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
return(ierrno);
}
/* now update the replacement node */
save_prev.if_parent = save_inx_rec.if_parent;
save_prev.if_right_node = save_inx_rec.if_right_node;
if (save_inx_rec.if_left_node != save_prev_ptr) {
save_prev.if_left_node = save_inx_rec.if_left_node;
save_prev.if_flags = 0;
}
else {
save_prev.if_flags &= ~(RTHRD | ETHRD);
}
if (iwrite_inx(db_control,&save_prev,save_prev_ptr))
return(ierrno);
/* get inorder successor and update its left thread pointer */
if (iget_next(db_control,&save_inx_rec))
return(ierrno);
irec->if_left_node = save_prev_ptr;
if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
return(ierrno);
}
db_control->df_flags |= DF_DELETE; /* flag record as deleted */
return(0);
} /* idelete */